package com.cloudweb.oa.controller;

import cn.js.fan.db.ListResult;
import cn.js.fan.util.ErrMsgException;
import cn.js.fan.util.ResKeyException;
import cn.js.fan.util.StrUtil;
import cn.js.fan.web.Global;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cloudweb.oa.api.IBasicSelectCtl;
import com.cloudweb.oa.service.MacroCtlService;
import com.cloudweb.oa.utils.ResponseUtil;
import com.cloudweb.oa.utils.SpringUtil;
import com.cloudweb.oa.vo.Result;
import com.cloudwebsoft.framework.base.QObjectMgr;
import com.cloudwebsoft.framework.db.JdbcTemplate;
import com.cloudwebsoft.framework.util.LogUtil;
import com.redmoon.oa.basic.SelectDb;
import com.redmoon.oa.basic.SelectMgr;
import com.redmoon.oa.basic.SelectOptionDb;
import com.redmoon.oa.flow.FormDb;
import com.redmoon.oa.flow.FormField;
import com.redmoon.oa.flow.macroctl.MacroCtlMgr;
import com.redmoon.oa.flow.macroctl.MacroCtlUnit;
import com.redmoon.oa.kernel.JobUnitDb;
import com.redmoon.oa.kernel.SchedulerManager;
import com.redmoon.oa.person.UserDb;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Iterator;
import java.util.Vector;

@Controller
@RequestMapping("/admin")
public class SchedulerController {
    @Autowired
    HttpServletRequest request;

    @Autowired
    private MacroCtlService macroCtlService;

    @ApiOperation(value = "列出调度", notes = "列出调度", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "页数", dataType = "Integer"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "Integer"),
    })
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PreAuthorize("hasAnyAuthority('admin')")
    @ResponseBody
    @RequestMapping(value = "/listJob", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8;", "application/json;charset=UTF-8;"})
    public Result<Object> listJob(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "20") Integer pageSize) {
        JSONObject json = new JSONObject();
        JobUnitDb jud = new JobUnitDb();
        JSONArray list = new JSONArray();
        String sql = "select ID from " + jud.getTable().getName() + " order by id desc";
        ListResult lr;
        try {
            lr = jud.listResult(new JdbcTemplate(), sql, page, pageSize);
            Vector v = lr.getResult();
            UserDb ud = new UserDb();
            for (Object o : v) {
                jud = (JobUnitDb) o;
                ud = ud.getUserDb(jud.getString("user_name"));
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("id", jud.getInt("id"));
                jsonObject.put("jobName", jud.get("job_name"));
                jsonObject.put("jobClass", jud.get("job_class"));
                jsonObject.put("cron", jud.getString("cron"));
                jsonObject.put("realName", ud.getRealName());
                list.add(jsonObject);
            }
        } catch (ResKeyException e) {
            return new Result<>(false, e.getMessage(request));
        }
        json.put("list", list);
        json.put("total", lr.getTotal());
        SchedulerManager sm = SchedulerManager.getInstance();
        json.put("statusName", sm.isStandby() ? "已暂停" : "运行中");
        return new Result<>(json);
    }

    @ApiOperation(value = "编辑调度页面", notes = "编辑调度页面", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", dataType = "Integer"),
    })
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PreAuthorize("hasAnyAuthority('admin')")
    @ResponseBody
    @RequestMapping(value = "/editJobPage", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8;", "application/json;charset=UTF-8;"})
    public Result<Object> editJobPage(@RequestParam int id) {
        JobUnitDb jud = new JobUnitDb();
        jud = (JobUnitDb) jud.getQObjectDb(id);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id", jud.getInt("id"));
        jsonObject.put("jobName", jud.get("job_name"));
        jsonObject.put("jobClass", jud.get("job_class"));
        jsonObject.put("cron", jud.getString("cron"));
        UserDb ud = new UserDb();
        ud = ud.getUserDb(jud.getString("user_name"));
        jsonObject.put("userName", ud.getName());
        jsonObject.put("realName", ud.getRealName());
        jsonObject.put("monthDay", jud.get("month_day"));
        jsonObject.put("dataMap", jud.get("data_map"));
        jsonObject.put("jobData", jud.getString("job_data"));

        String strDataMap = jud.getString("data_map");

        String cron = jud.getString("cron");
        jsonObject.put("cron", cron);

        String[] ary = cron.split(" ");
        if (ary.length > 0) {
            if (ary[0].length() == 1) {
                ary[0] = "0" + ary[0];
            }
            if (ary[1].length() == 1) {
                ary[1] = "0" + ary[1];
            }
            if (ary[2].length() == 1) {
                ary[2] = "0" + ary[2];
            }
        }

        String interval = "", intervalType = "";
        int p = ary[0].indexOf("/");
        if (p != -1) {
            interval = ary[0].substring(p + 1);
            intervalType = "s";
        }
        p = ary[1].indexOf("/");
        if (p != -1) {
            interval = ary[1].substring(p + 1);
            intervalType = "m";
        }
        p = ary[2].indexOf("/");
        if (p != -1) {
            interval = ary[2].substring(p + 1);
            intervalType = "h";
        }
        p = ary[3].indexOf("/");
        if (p != -1) {
            interval = ary[3].substring(p + 1);
            intervalType = "d";
        }

        String monthDay = StrUtil.getNullStr(jud.getString("month_day"));
        String[] w = ary[5].split(",");

        String t = "";
        if ("".equals(intervalType)) {
            t = ary[2] + ":" + ary[1] + ":" + ary[0];
        }

        int kind = 3;
        if (!"".equals(monthDay)) {
            kind = 0;
        } else if (!"?".equals(w[0])) {
            kind = 1;
        } else if (!"".equals(interval)) {
            kind = 2;
        }
        jsonObject.put("kind", kind);
        jsonObject.put("time", t);
        jsonObject.put("intervalType", intervalType);
        jsonObject.put("interval", interval);
        jsonObject.put("weekDay", w);

        String formCode = "";
        if ("com.redmoon.oa.job.SynThirdPartyDataJob".equals(jud.get("job_class"))) {
            JSONObject dataMap = JSONObject.parseObject(strDataMap);
            String dbSource = dataMap.getString("dbSource");
            String primaryKey = dataMap.getString("primaryKey");
            String foreignKey = dataMap.getString("foreignKey");
            formCode = dataMap.getString("formCode");
            String table = dataMap.getString("table");

            jsonObject.put("dbSource", dbSource);
            jsonObject.put("primaryKey", primaryKey);
            jsonObject.put("foreignKey", foreignKey);
            jsonObject.put("formCode", formCode);
            jsonObject.put("table", table);

            FormDb fd = new FormDb();
            fd = fd.getFormDb(formCode);

            JSONObject fieldMap = dataMap.getJSONObject("fieldMap");
            jsonObject.put("fieldMap", fieldMap);

            // 清洗
            JSONArray optionsAry = new JSONArray();
            SelectMgr sm = new SelectMgr();
            MacroCtlMgr mm = new MacroCtlMgr();
            JSONArray aryClean = dataMap.getJSONArray("cleanMap");

            MacroCtlService macroCtlService = SpringUtil.getBean(MacroCtlService.class);
            IBasicSelectCtl basicSelectCtl = macroCtlService.getBasicSelectCtl();
            for (FormField ff : fd.getFields()) {
                if (ff.getType().equals(FormField.TYPE_MACRO)) {
                    MacroCtlUnit mu = mm.getMacroCtlUnit(ff.getMacroType());
                    if (mu != null && "macro_flow_select".equals(mu.getCode())) {
                        boolean isClean = false;
                        JSONObject json = null;
                        if (aryClean != null) {
                            for (int i = 0; i < aryClean.size(); i++) {
                                json = aryClean.getJSONObject(i);
                                if (ff.getName().equals(json.get("fieldName"))) {
                                    isClean = true;
                                    break;
                                }
                            }
                        }

                        String basicCode = basicSelectCtl.getCode(ff);
                        SelectDb sd = sm.getSelect(basicCode);
                        if (sd.getType() == SelectDb.TYPE_TREE) {
                            continue;
                        }

                        JSONObject jsonField = new JSONObject();
                        jsonField.put("fieldName", ff.getName());
                        jsonField.put("title", ff.getTitle());
                        jsonField.put("checked", true);
                        optionsAry.add(jsonField);

                        JSONArray options = new JSONArray();
                        jsonField.put("options", options);

                        Vector<SelectOptionDb> v = sd.getOptions(new JdbcTemplate());
                        for (SelectOptionDb sod : v) {
                            if (!sod.isOpen()) {
                                continue;
                            }

                            String val = sod.getValue();
                            String otherVal = "";
                            if (isClean && json!=null) {
                                Iterator keys = json.keySet().iterator();
                                while (keys.hasNext()) {
                                    String key = (String)keys.next();
                                    String toVal = json.getString(key);
                                    if (val.equals(toVal)) {
                                        otherVal = key;
                                        break;
                                    }
                                }
                            }

                            JSONObject jsonOpt = new JSONObject();
                            jsonOpt.put("name", sod.getName());
                            jsonOpt.put("value", sod.getValue());
                            jsonOpt.put("otherVal", otherVal);
                            options.add(jsonOpt);
                        }
                    }
                }
            }

            jsonObject.put("basicDataOptions", optionsAry);
        } else if ("com.redmoon.oa.job.WorkflowJob".equals(jud.get("job_class"))) {
            jsonObject.put("flowCode", strDataMap);
        }

        return new Result<>(jsonObject);
    }

    @ApiOperation(value = "删除调度", notes = "删除调度", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", dataType = "Integer"),
    })
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PreAuthorize("hasAnyAuthority('admin')")
    @ResponseBody
    @RequestMapping(value = "/delJob", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8;", "application/json;charset=UTF-8;"})
    public Result<Object> delJob(@RequestParam int id) {
        JobUnitDb jud = new JobUnitDb();
        jud = (JobUnitDb) jud.getQObjectDb(id);
        boolean re;
        try {
            re = jud.del();
        } catch (ResKeyException e) {
            return new Result<>(false, e.getMessage(request));
        }
        return new Result<>(re);
    }

    @ApiOperation(value = "创建调度", notes = "创建调度", httpMethod = "POST")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PreAuthorize("hasAnyAuthority('admin')")
    @ResponseBody
    @RequestMapping(value = "/createJob", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8;", "application/json;charset=UTF-8;"})
    public Result<Object> createJob() {
        QObjectMgr qom = new QObjectMgr();
        JobUnitDb ju = new JobUnitDb();
        boolean re;
        try {
            re = qom.create(request, ju, "scheduler_add");
        } catch (ErrMsgException e) {
            return new Result<>(false, e.getMessage());
        }
        return new Result<>(re);
    }

    @ApiOperation(value = "修改调度", notes = "修改调度", httpMethod = "POST")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PreAuthorize("hasAnyAuthority('admin')")
    @ResponseBody
    @RequestMapping(value = "/updateJob", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8;", "application/json;charset=UTF-8;"})
    public Result<Object> updateJob(@RequestParam Integer id) {
        QObjectMgr qom = new QObjectMgr();
        JobUnitDb ju = new JobUnitDb();
        boolean re;
        try {
            ju = (JobUnitDb)ju.getQObjectDb(new Integer(id));
            re = qom.save(request, ju, "scheduler_edit");
        } catch (ErrMsgException e) {
            return new Result<>(false, e.getMessage());
        }
        return new Result<>(re);
    }

    @ApiOperation(value = "列出基础数据用于数据订阅清洗", notes = "列出基础数据用于数据订阅清洗", httpMethod = "POST")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PreAuthorize("hasAnyAuthority('admin')")
    @ResponseBody
    @RequestMapping(value = "/listBasicDataOptions", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8;", "application/json;charset=UTF-8;"})
    public Result<Object> listBasicDataOptions(@RequestParam String formCode) {
        FormDb fd = new FormDb();
        fd = fd.getFormDb(formCode);

        // 清洗
        JSONArray ary = new JSONArray();
        SelectMgr sm = new SelectMgr();
        MacroCtlMgr mm = new MacroCtlMgr();

        MacroCtlService macroCtlService = SpringUtil.getBean(MacroCtlService.class);
        IBasicSelectCtl basicSelectCtl = macroCtlService.getBasicSelectCtl();
        for (FormField ff : fd.getFields()) {
            if (ff.getType().equals(FormField.TYPE_MACRO)) {
                MacroCtlUnit mu = mm.getMacroCtlUnit(ff.getMacroType());
                if (mu != null && "macro_flow_select".equals(mu.getCode())) {
                    String basicCode = basicSelectCtl.getCode(ff);
                    SelectDb sd = sm.getSelect(basicCode);
                    if (sd.getType() == SelectDb.TYPE_TREE) {
                        continue;
                    }

                    JSONObject jsonField = new JSONObject();
                    jsonField.put("fieldName", ff.getName());
                    jsonField.put("title", ff.getTitle());
                    jsonField.put("checked", false);
                    ary.add(jsonField);

                    JSONArray options = new JSONArray();
                    jsonField.put("options", options);

                    Vector<SelectOptionDb> v = sd.getOptions(new JdbcTemplate());
                    for (SelectOptionDb sod : v) {
                        if (!sod.isOpen()) {
                            continue;
                        }

                        JSONObject jsonOpt = new JSONObject();
                        jsonOpt.put("name", sod.getName());
                        jsonOpt.put("value", sod.getValue());
                        options.add(jsonOpt);
                    }
                }
            }
        }
        return new Result<>(ary);
    }

    @ApiOperation(value = "恢复调度", notes = "恢复调度", httpMethod = "POST")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PreAuthorize("hasAnyAuthority('admin')")
    @ResponseBody
    @RequestMapping(value = "/resumeJob", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8;", "application/json;charset=UTF-8;"})
    public Result<Object> resumeJob() {
        if (Global.getInstance().isSchedule()) {
            SchedulerManager sm = SchedulerManager.getInstance();
            // sm.resumeAll();
            sm.start();
            return new Result<>(true, "调度已恢复");
        } else {
            return new Result<>(false, "调度未启用，请先在系统变量中启用调度");
        }
    }

    @ApiOperation(value = "停止调度", notes = "停止调度", httpMethod = "POST")
    @ApiResponses({@ApiResponse(code = 200, message = "操作成功")})
    @PreAuthorize("hasAnyAuthority('admin')")
    @ResponseBody
    @RequestMapping(value = "/stopJob", method = RequestMethod.POST, produces = {"text/html;charset=UTF-8;", "application/json;charset=UTF-8;"})
    public Result<Object> stopJob() {
        if (Global.getInstance().isSchedule()) {
            SchedulerManager sm = SchedulerManager.getInstance();
            sm.standby();
            return new Result<>(true, "调度已暂停");
        } else {
            return new Result<>(false, "调度未启用，请先在系统变量中启用调度");
        }
    }
}
